// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包asn1实现对DER编码的ASN的解析。1数据结构，
// 定义见ITU-T Rec X.690。
// 
// 另请参见《ASN子集的外行指南》。1、BER和DER，“
// http:
package asn1

// ASN。1是用于指定抽象对象的语法，BER、DER、PER、XER等
// 是这些对象的不同编码格式。在这里，我们将处理
// 和DER，即特殊的编码规则。DER在X.509中使用是因为
// 它的解析速度很快，而且与BER不同，它对每个对象都有唯一的编码。
// 在计算对象的哈希值时，得到的
// 字节的两端必须相同，并且DER消除了这个误差范围，这一点很重要。
// 
// ASN。1是非常复杂的，这个包并不试图以任何方式实现
// 所有内容。

import (
	"errors"
	"fmt"
	"math"
	"math/big"
	"reflect"
	"strconv"
	"time"
	"unicode/utf16"
	"unicode/utf8"
)

// 结构错误表明ASN。1数据有效，但接收数据的Go类型
// 不匹配。
type StructuralError struct {
	Msg string
}

func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg }

// 语法错误提示ASN。1数据无效。
type SyntaxError struct {
	Msg string
}

func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg }

// 我们从依次处理每一个基元类型开始。

// 布尔值

func parseBool(bytes []byte) (ret bool, err error) {
	if len(bytes) != 1 {
		err = SyntaxError{"invalid boolean"}
		return
	}

	// 命令要求“如果编码代表布尔值TRUE，
	// 其单个内容八位字节应将所有八位设置为一。”
	// 因此只有0和255是有效的编码值。
	switch bytes[0] {
	case 0:
		ret = false
	case 0xff:
		ret = true
	default:
		err = SyntaxError{"invalid boolean"}
	}

	return
}

// 整数

// 如果给定字节是有效的DER编码
// 整数，则checkInteger返回nil，否则返回错误。
func checkInteger(bytes []byte) error {
	if len(bytes) == 0 {
		return StructuralError{"empty integer"}
	}
	if len(bytes) == 1 {
		return nil
	}
	if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) {
		return StructuralError{"integer not minimally-encoded"}
	}
	return nil
}

// parseInt64将给定字节视为一个大端有符号整数，
// 返回结果。
func parseInt64(bytes []byte) (ret int64, err error) {
	err = checkInteger(bytes)
	if err != nil {
		return
	}
	if len(bytes) > 8 {
		// 在这种情况下，我们将使int64溢出。
		err = StructuralError{"integer too large"}
		return
	}
	for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
		ret <<= 8
		ret |= int64(bytes[bytesRead])
	}

	// 上下移动以签署扩展结果。
	ret <<= 64 - uint8(len(bytes))*8
	ret >>= 64 - uint8(len(bytes))*8
	return
}

// parseInt将给定字节视为一个大端有符号整数，并返回
// 结果。
func parseInt32(bytes []byte) (int32, error) {
	if err := checkInteger(bytes); err != nil {
		return 0, err
	}
	ret64, err := parseInt64(bytes)
	if err != nil {
		return 0, err
	}
	if ret64 != int64(int32(ret64)) {
		return 0, StructuralError{"integer too large"}
	}
	return int32(ret64), nil
}

var bigOne = big.NewInt(1)

// parseBigInt将给定字节视为一个大端有符号整数，并返回
// 结果。这是一个负数。
func parseBigInt(bytes []byte) (*big.Int, error) {
	if err := checkInteger(bytes); err != nil {
		return nil, err
	}
	ret := new(big.Int)
	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
		notBytes := make([]byte, len(bytes))
		for i := range notBytes {
			notBytes[i] = ^bytes[i]
		}
		ret.SetBytes(notBytes)
		ret.Add(ret, bigOne)
		ret.Neg(ret)
		return ret, nil
	}
	ret.SetBytes(bytes)
	return ret, nil
}

// 位字符串

// 位字符串是需要ASN时使用的结构。1位字符串类型。
// 位字符串被填充到内存中最接近的字节，并记录
// 有效位的数量。填充位将为零。
type BitString struct {
	Bytes     []byte // 位压缩为字节。
	BitLength int    // 以位为单位的长度。
}

// At返回给定索引处的位。如果索引超出范围，则返回false。shuan xiang jian defg
func (b BitString) At(i int) int {
	if i < 0 || i >= b.BitLength {
		return 0
	}
	x := i / 8
	y := 7 - uint(i%8)
	return int(b.Bytes[x]>>y) & 1
}

// 片可以与位字符串共享内存。
func (b BitString) RightAlign() []byte {
	shift := uint(8 - (b.BitLength % 8))
	if shift == 8 || len(b.Bytes) == 0 {
		return b.Bytes
	}

	a := make([]byte, len(b.Bytes))
	a[0] = b.Bytes[0] >> shift
	for i := 1; i < len(b.Bytes); i++ {
		a[i] = b.Bytes[i-1] << (8 - shift)
		a[i] |= b.Bytes[i] >> shift
	}

	return a
}

// parseBitString解析ASN。从给定字节片中提取1位字符串并返回。
func parseBitString(bytes []byte) (ret BitString, err error) {
	if len(bytes) == 0 {
		err = SyntaxError{"zero length BIT STRING"}
		return
	}
	paddingBits := int(bytes[0])
	if paddingBits > 7 ||
		len(bytes) == 1 && paddingBits > 0 ||
		bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
		err = SyntaxError{"invalid padding bits in BIT STRING"}
		return
	}
	ret.BitLength = (len(bytes)-1)*8 - paddingBits
	ret.Bytes = bytes[1:]
	return
}

// NULL 

// NullRawValue是一个RawValue，其标记设置为ASN。1个空类型标记（5）。
var NullRawValue = RawValue{Tag: TagNull}

// NullBytes包含表示DER编码ASN的字节。1空类型。
var NullBytes = []byte{TagNull, 0}

// 对象标识符

// 对象标识符表示ASN。1对象标识符。
type ObjectIdentifier []int

// Equal报告oi和other是否代表相同的标识符。
func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
	if len(oi) != len(other) {
		return false
	}
	for i := 0; i < len(oi); i++ {
		if oi[i] != other[i] {
			return false
		}
	}

	return true
}

func (oi ObjectIdentifier) String() string {
	var s string

	for i, v := range oi {
		if i > 0 {
			s += "."
		}
		s += strconv.Itoa(v)
	}

	return s
}

// parseObjectIdentifier从给定字节解析对象标识符，并返回它。对象标识符是在层次结构中分配的可变长度整数
// 序列。
func parseObjectIdentifier(bytes []byte) (s ObjectIdentifier, err error) {
	if len(bytes) == 0 {
		err = SyntaxError{"zero length OBJECT IDENTIFIER"}
		return
	}

	// 在最坏的情况下，我们从第一个字节中得到两个元素（即
	// 编码不同），然后每个变量都是一个字节长。
	s = make([]int, len(bytes)+1)

	// 第一个变量是40*值1+值2：
	// 根据此包装，值1只能取值0、1和2。
	// 当value1=0或value1=1时，则value2<=39。当value1=2时，
	// 则对value2没有限制。
	v, offset, err := parseBase128Int(bytes, 0)
	if err != nil {
		return
	}
	if v < 80 {
		s[0] = v / 40
		s[1] = v % 40
	} else {
		s[0] = 2
		s[1] = v - 80
	}

	i := 2
	for ; offset < len(bytes); i++ {
		v, offset, err = parseBase128Int(bytes, offset)
		if err != nil {
			return
		}
		s[i] = v
	}
	s = s[0:i]
	return
}

// 枚举的

// 枚举的表示为纯整数。
type Enumerated int

// 标志

// 标志接受任何数据，如果存在，则设置为true。
type Flag bool

// parseBase128Int从
// 给定字节片中的给定偏移量解析一个base-128编码的int。它返回值和新的偏移量。
func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
	offset = initOffset
	var ret64 int64
	for shifted := 0; offset < len(bytes); shifted++ {
		// 5*7位/字节==35位数据
		// 因此，对于int32 
		if shifted == 5 {
			err = StructuralError{"base 128 integer too large"}
			return
		}
		ret64 <<= 7
		b := bytes[offset]
		// 整数而言，表示不是非最小的，就是太大了。整数应进行最小编码，因此前导八位字节应为
		// 永远不要是0x80 
		if shifted == 0 && b == 0x80 {
			err = SyntaxError{"integer is not minimally encoded"}
			return
		}
		ret64 |= int64(b & 0x7f)
		offset++
		if b&0x80 == 0 {
			ret = int(ret64)
			// 确保返回值适合所有平台上的整数
			if ret64 > math.MaxInt32 {
				err = StructuralError{"base 128 integer too large"}
			}
			return
		}
	}
	err = SyntaxError{"truncated base 128 integer"}
	return
}

// UTCTime 

func parseUTCTime(bytes []byte) (ret time.Time, err error) {
	s := string(bytes)

	formatStr := "0601021504Z0700"
	ret, err = time.Parse(formatStr, s)
	if err != nil {
		formatStr = "060102150405Z0700"
		ret, err = time.Parse(formatStr, s)
	}
	if err != nil {
		return
	}

	if serialized := ret.Format(formatStr); serialized != s {
		err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
		return
	}

	if ret.Year() >= 2050 {
		// UTCTime仅编码2050年之前的时间。请参阅https:
		ret = ret.AddDate(-100, 0, 0)
	}

	return
}

// parseGeneralizedTime从给定字节片
// 解析GeneralizedTime并返回结果时间。
func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
	const formatStr = "20060102150405Z0700"
	s := string(bytes)

	if ret, err = time.Parse(formatStr, s); err != nil {
		return
	}

	if serialized := ret.Format(formatStr); serialized != s {
		err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized)
	}

	return
}

// 数值字符串

// 解析数值字符串解析ASN。从给定字节数组
// 中提取1个NumericString并返回它。
func parseNumericString(bytes []byte) (ret string, err error) {
	for _, b := range bytes {
		if !isNumeric(b) {
			return "", SyntaxError{"NumericString contains invalid character"}
		}
	}
	return string(bytes), nil
}

// isNumeric报告给定的b是否在ASN中。1个数字字符串集。
func isNumeric(b byte) bool {
	return '0' <= b && b <= '9' ||
		b == ' '
}

// PrintableString 

// parsePrintableString解析ASN。从给定字节
// 数组中提取1个可打印字符串，并返回该字符串。
func parsePrintableString(bytes []byte) (ret string, err error) {
	for _, b := range bytes {
		if !isPrintable(b, allowAsterisk, allowAmpersand) {
			err = SyntaxError{"PrintableString contains invalid character"}
			return
		}
	}
	ret = string(bytes)
	return
}

type asteriskFlag bool
type ampersandFlag bool

const (
	allowAsterisk  asteriskFlag = true
	rejectAsterisk asteriskFlag = false

	allowAmpersand  ampersandFlag = true
	rejectAmpersand ampersandFlag = false
)

// 可打印报告给定的b是否在ASN中。1个可打印字符串集。
// 如果星号为AllowsRisk，则也允许使用“*”，反映现有
// 惯例。如果允许使用符号AND，则也允许使用“&”。
func isPrintable(b byte, asterisk asteriskFlag, ampersand ampersandFlag) bool {
	return 'a' <= b && b <= 'z' ||
		'A' <= b && b <= 'Z' ||
		'0' <= b && b <= '9' ||
		'\'' <= b && b <= ')' ||
		'+' <= b && b <= '/' ||
		b == ' ' ||
		b == ':' ||
		b == '=' ||
		b == '?' ||
		// 从技术上讲，这在可打印字符串中是不允许的。
		// 但是，带有通配符字符串的x509证书不能使用正确的字符串类型，因此我们允许使用。
		(bool(asterisk) && b == '*') ||
		// 这在技术上也是不允许的。然而，并不是
		// 它只是比较常见，但也有一些包含它的CA证书。至少
		// 其中一个将在2027年前到期。
		(bool(ampersand) && b == '&')
}

// IA5String 

// parseIA5String解析ASN。1从给定的
// 字节片中提取IA5String（ASCII字符串），并返回它。
func parseIA5String(bytes []byte) (ret string, err error) {
	for _, b := range bytes {
		if b >= utf8.RuneSelf {
			err = SyntaxError{"IA5String contains invalid character"}
			return
		}
	}
	ret = string(bytes)
	return
}

// T61字符串

// ParseT61字符串解析ASN。1 T61从给定的
// 字节片中提取字符串（8位干净字符串），并返回它。
func parseT61String(bytes []byte) (ret string, err error) {
	return string(bytes), nil
}

// UTF8String 

// parseUTF8String解析ASN。从给定字节
// 数组中提取1个UTF8String（原始UTF-8）并返回它。
func parseUTF8String(bytes []byte) (ret string, err error) {
	if !utf8.Valid(bytes) {
		return "", errors.New("asn1: invalid UTF-8 string")
	}
	return string(bytes), nil
}

// BMPString 

// parseBMPString解析ASN。1个BMPString（
// ISO/IEC/ITU 10646-1的基本多语言平面）从给定的字节片返回。
func parseBMPString(bmpString []byte) (string, error) {
	if len(bmpString)%2 != 0 {
		return "", errors.New("pkcs12: odd-length BMP string")
	}

	// 如果有带式终端。
	if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
		bmpString = bmpString[:l-2]
	}

	s := make([]uint16, 0, len(bmpString)/2)
	for len(bmpString) > 0 {
		s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
		bmpString = bmpString[2:]
	}

	return string(utf16.Decode(s)), nil
}

// 原始值表示未编码的ASN。1个物体。
type RawValue struct {
	Class, Tag int
	IsCompound bool
	Bytes      []byte
	FullBytes  []byte // 包括标记和长度
}

// RawContent用于表示未编码的DER数据需要为结构保留
// 数据。要使用它，结构的第一个字段必须具有
// 此类型。任何其他字段具有此类型都是错误的。
type RawContent []byte

// 标记

// parseTagAndLength解析ASN。从给定偏移量
// 到字节片的1个标记和长度对。它返回解析后的数据和新的偏移量。SET和
// SET OF（tag 17）被映射到SEQUENCE and SEQUENCE OF（tag 16），因为我们
// 在这段代码中不区分有序和无序对象。
func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) {
	offset = initOffset
	// parseTagAndLength在没有至少一个
	// 字节读取的情况下不应被调用。因此，该检查是为了确保健壮性：如果设置了最下面的五位，那么标签号实际上是以128为基数的
	if offset >= len(bytes) {
		err = errors.New("asn1: internal error in parseTagAndLength")
		return
	}
	b := bytes[offset]
	offset++
	ret.class = int(b >> 6)
	ret.isCompound = b&0x20 == 0x20
	ret.tag = int(b & 0x1f)

	// 编码后
	if ret.tag == 0x1f {
		ret.tag, offset, err = parseBase128Int(bytes, offset)
		if err != nil {
			return
		}
		// 标签应以最小形式编码。
		if ret.tag < 0x1f {
			err = SyntaxError{"non-minimal tag"}
			return
		}
	}
	if offset >= len(bytes) {
		err = SyntaxError{"truncated tag or length"}
		return
	}
	b = bytes[offset]
	offset++
	if b&0x80 == 0 {
		// 长度在底部7位编码。
		ret.length = int(b & 0x7f)
	} else {
		// 底部7位给出要跟随的长度字节数。
		numBytes := int(b & 0x7f)
		if numBytes == 0 {
			err = SyntaxError{"indefinite length found (not DER)"}
			return
		}
		ret.length = 0
		for i := 0; i < numBytes; i++ {
			if offset >= len(bytes) {
				err = SyntaxError{"truncated tag or length"}
				return
			}
			b = bytes[offset]
			offset++
			if ret.length >= 1<<23 {
				// 我们不能在没有
				// 溢出的情况下将ret.length向上移动。
				err = StructuralError{"length too large"}
				return
			}
			ret.length <<= 8
			ret.length |= int(b)
			if ret.length == 0 {
				// DER要求长度最小。
				err = StructuralError{"superfluous leading zeros in length"}
				return
			}
		}
		// 短长度必须以短形式编码。
		if ret.length < 0x80 {
			err = StructuralError{"non-minimal length"}
			return
		}
	}

	return
}

// parseSequenceOf用于值序列和值集。它试图解析
// 许多ASN。1从给定字节片返回值，并将其作为给定类型的Go值的
// 片返回。
func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) {
	matchAny, expectedTag, compoundType, ok := getUniversalType(elemType)
	if !ok {
		err = StructuralError{"unknown Go type for slice"}
		return
	}

	// 首先我们迭代输入并计算元素的数量，
	// 检查每种情况下的类型是否正确。
	numElements := 0
	for offset := 0; offset < len(bytes); {
		var t tagAndLength
		t, offset, err = parseTagAndLength(bytes, offset)
		if err != nil {
			return
		}
		switch t.tag {
		case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
			// 我们假设其他各种字符串类型都是
			// 可打印的字符串，这样它们的序列就可以被
			// 解析为[]字符串。
			t.tag = TagPrintableString
		case TagGeneralizedTime, TagUTCTime:
			// 同样地，两种时间类型被视为相同的。
			t.tag = TagUTCTime
		}

		if !matchAny && (t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag) {
			err = StructuralError{"sequence tag mismatch"}
			return
		}
		if invalidLength(offset, t.length, len(bytes)) {
			err = SyntaxError{"truncated sequence"}
			return
		}
		offset += t.length
		numElements++
	}
	ret = reflect.MakeSlice(sliceType, numElements, numElements)
	params := fieldParameters{}
	offset := 0
	for i := 0; i < numElements; i++ {
		offset, err = parseField(ret.Index(i), bytes, offset, params)
		if err != nil {
			return
		}
	}
	return
}

var (
	bitStringType        = reflect.TypeOf(BitString{})
	objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
	enumeratedType       = reflect.TypeOf(Enumerated(0))
	flagType             = reflect.TypeOf(Flag(false))
	timeType             = reflect.TypeOf(time.Time{})
	rawValueType         = reflect.TypeOf(RawValue{})
	rawContentsType      = reflect.TypeOf(RawContent(nil))
	bigIntType           = reflect.TypeOf(new(big.Int))
)

// invalidLength报告偏移量+长度>切片长度，或者
// 加法是否会溢出。
func invalidLength(offset, length, sliceLength int) bool {
	return offset+length < offset || offset+length > sliceLength
}

// parseField是主要的解析函数。给定一个字节片和一个偏移量
// 到数组中，它将尝试解析一个合适的ASN。1输出值并将其存储在给定值中
// 中。
func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) {
	offset = initOffset
	fieldType := v.Type()

	// 如果我们已经用完了数据，可能是因为最后有可选元素。
	if offset == len(bytes) {
		if !setDefaultValue(v, params) {
			err = SyntaxError{"sequence truncated"}
		}
		return
	}

	// 处理任何类型的问题。
	if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
		var t tagAndLength
		t, offset, err = parseTagAndLength(bytes, offset)
		if err != nil {
			return
		}
		if invalidLength(offset, t.length, len(bytes)) {
			err = SyntaxError{"data truncated"}
			return
		}
		var result any
		if !t.isCompound && t.class == ClassUniversal {
			innerBytes := bytes[offset : offset+t.length]
			switch t.tag {
			case TagPrintableString:
				result, err = parsePrintableString(innerBytes)
			case TagNumericString:
				result, err = parseNumericString(innerBytes)
			case TagIA5String:
				result, err = parseIA5String(innerBytes)
			case TagT61String:
				result, err = parseT61String(innerBytes)
			case TagUTF8String:
				result, err = parseUTF8String(innerBytes)
			case TagInteger:
				result, err = parseInt64(innerBytes)
			case TagBitString:
				result, err = parseBitString(innerBytes)
			case TagOID:
				result, err = parseObjectIdentifier(innerBytes)
			case TagUTCTime:
				result, err = parseUTCTime(innerBytes)
			case TagGeneralizedTime:
				result, err = parseGeneralizedTime(innerBytes)
			case TagOctetString:
				result = innerBytes
			case TagBMPString:
				result, err = parseBMPString(innerBytes)
			default:
				// 如果我们不知道如何处理该类型，我们只会将值保留为nil。
			}
		}
		offset += t.length
		if err != nil {
			return
		}
		if result != nil {
			v.Set(reflect.ValueOf(result))
		}
		return
	}

	t, offset, err := parseTagAndLength(bytes, offset)
	if err != nil {
		return
	}
	if params.explicit {
		expectedClass := ClassContextSpecific
		if params.application {
			expectedClass = ClassApplication
		}
		if offset == len(bytes) {
			err = StructuralError{"explicit tag has no child"}
			return
		}
		if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) {
			if fieldType == rawValueType {
				// 不应为rawValue分析内部元素。
			} else if t.length > 0 {
				t, offset, err = parseTagAndLength(bytes, offset)
				if err != nil {
					return
				}
			} else {
				if fieldType != flagType {
					err = StructuralError{"zero length explicit tag was not an asn1.Flag"}
					return
				}
				v.SetBool(true)
				return
			}
		} else {
			// 标记不匹配，可能是可选元素。
			ok := setDefaultValue(v, params)
			if ok {
				offset = initOffset
			} else {
				err = StructuralError{"explicitly tagged member didn't match"}
			}
			return
		}
	}

	matchAny, universalTag, compoundType, ok1 := getUniversalType(fieldType)
	if !ok1 {
		err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)}
		return
	}

	// 字符串的特殊情况：所有ASN。1字符串类型映射到Go 
	// 类型字符串。getUniversalType在看到字符串时返回可打印字符串
	// 的标记，因此如果我们在
	// 导线上看到不同的字符串类型，我们会将通用类型更改为匹配。
	if universalTag == TagPrintableString {
		if t.class == ClassUniversal {
			switch t.tag {
			case TagIA5String, TagGeneralString, TagT61String, TagUTF8String, TagNumericString, TagBMPString:
				universalTag = t.tag
			}
		} else if params.stringType != 0 {
			universalTag = params.stringType
		}
	}

	// 时间的特例：UTCTime和GeneralizedTime都映射到
	// Go-type-time。时间
	if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal {
		universalTag = TagGeneralizedTime
	}

	if params.set {
		universalTag = TagSet
	}

	matchAnyClassAndTag := matchAny
	expectedClass := ClassUniversal
	expectedTag := universalTag

	if !params.explicit && params.tag != nil {
		expectedClass = ClassContextSpecific
		expectedTag = *params.tag
		matchAnyClassAndTag = false
	}

	if !params.explicit && params.application && params.tag != nil {
		expectedClass = ClassApplication
		expectedTag = *params.tag
		matchAnyClassAndTag = false
	}

	if !params.explicit && params.private && params.tag != nil {
		expectedClass = ClassPrivate
		expectedTag = *params.tag
		matchAnyClassAndTag = false
	}

	// 我们现在已经打开了任何显式标记。
	if !matchAnyClassAndTag && (t.class != expectedClass || t.tag != expectedTag) ||
		(!matchAny && t.isCompound != compoundType) {
		// 标记不匹配。同样，它可能是一个可选元素。
		ok := setDefaultValue(v, params)
		if ok {
			offset = initOffset
		} else {
			err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)}
		}
		return
	}
	if invalidLength(offset, t.length, len(bytes)) {
		err = SyntaxError{"data truncated"}
		return
	}
	innerBytes := bytes[offset : offset+t.length]
	offset += t.length

	// 我们首先处理这个包中定义的结构。
	switch v := v.Addr().Interface().(type) {
	case *RawValue:
		*v = RawValue{t.class, t.tag, t.isCompound, innerBytes, bytes[initOffset:offset]}
		return
	case *ObjectIdentifier:
		*v, err = parseObjectIdentifier(innerBytes)
		return
	case *BitString:
		*v, err = parseBitString(innerBytes)
		return
	case *time.Time:
		if universalTag == TagUTCTime {
			*v, err = parseUTCTime(innerBytes)
			return
		}
		*v, err = parseGeneralizedTime(innerBytes)
		return
	case *Enumerated:
		parsedInt, err1 := parseInt32(innerBytes)
		if err1 == nil {
			*v = Enumerated(parsedInt)
		}
		err = err1
		return
	case *Flag:
		*v = true
		return
	case **big.Int:
		parsedInt, err1 := parseBigInt(innerBytes)
		if err1 == nil {
			*v = parsedInt
		}
		err = err1
		return
	}
	switch val := v; val.Kind() {
	case reflect.Bool:
		parsedBool, err1 := parseBool(innerBytes)
		if err1 == nil {
			val.SetBool(parsedBool)
		}
		err = err1
		return
	case reflect.Int, reflect.Int32, reflect.Int64:
		if val.Type().Size() == 4 {
			parsedInt, err1 := parseInt32(innerBytes)
			if err1 == nil {
				val.SetInt(int64(parsedInt))
			}
			err = err1
		} else {
			parsedInt, err1 := parseInt64(innerBytes)
			if err1 == nil {
				val.SetInt(parsedInt)
			}
			err = err1
		}
		return
	// TODO（dfc）添加对剩余整数类型的支持
	case reflect.Struct:
		structType := fieldType

		for i := 0; i < structType.NumField(); i++ {
			if !structType.Field(i).IsExported() {
				err = StructuralError{"struct contains unexported fields"}
				return
			}
		}

		if structType.NumField() > 0 &&
			structType.Field(0).Type == rawContentsType {
			bytes := bytes[initOffset:offset]
			val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
		}

		innerOffset := 0
		for i := 0; i < structType.NumField(); i++ {
			field := structType.Field(i)
			if i == 0 && field.Type == rawContentsType {
				continue
			}
			innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1")))
			if err != nil {
				return
			}
		}
		// 我们允许在序列末尾添加额外字节，因为随着
		// 在末尾添加元素。
		// 版本号的增加，X.509中已经使用了
		return
	case reflect.Slice:
		sliceType := fieldType
		if sliceType.Elem().Kind() == reflect.Uint8 {
			val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
			reflect.Copy(val, reflect.ValueOf(innerBytes))
			return
		}
		newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
		if err1 == nil {
			val.Set(newSlice)
		}
		err = err1
		return
	case reflect.String:
		var v string
		switch universalTag {
		case TagPrintableString:
			v, err = parsePrintableString(innerBytes)
		case TagNumericString:
			v, err = parseNumericString(innerBytes)
		case TagIA5String:
			v, err = parseIA5String(innerBytes)
		case TagT61String:
			v, err = parseT61String(innerBytes)
		case TagUTF8String:
			v, err = parseUTF8String(innerBytes)
		case TagGeneralString:
			// 通用字符串在ISO-2022/ECMA-35中指定，
			// 简要回顾表明，它包括允许编码更改中间字符串的结构
			// 和
			// 这样的结构。我们放弃并将其作为8位字符串传递。
			v, err = parseT61String(innerBytes)
		case TagBMPString:
			v, err = parseBMPString(innerBytes)

		default:
			err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
		}
		if err == nil {
			val.SetString(v)
		}
		return
	}
	err = StructuralError{"unsupported: " + v.Type().String()}
	return
}

// canHaveDefaultValue报告k是否是我们将为其设置默认值的类型。（本质上是一个有符号整数。）
func canHaveDefaultValue(k reflect.Kind) bool {
	switch k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return true
	}

	return false
}

// setDefaultValue用于将标签字符串中的默认值安装到
// 值中。如果该字段是可选的，即使未提供默认值
// 或未能将其安装到该值中，也会成功。
func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
	if !params.optional {
		return
	}
	ok = true
	if params.defaultValue == nil {
		return
	}
	if canHaveDefaultValue(v.Kind()) {
		v.SetInt(*params.defaultValue)
	}
	return
}

// Unmarshal解析DER编码的ASN。1数据结构b 
// 并使用reflect包填充val指向的任意值。
// 由于解组器使用reflect包，因此写入的结构
// 必须使用大写字段名。如果val 
// 为零或不是指针，则解组返回错误。
// 
// 解析b后，剩余的、未用于填充
// val的字节将以rest返回。将序列解析为结构时，序列的任何尾随元素如果在val中没有匹配的字段，将不包括在rest中，因为它们被视为序列的有效元素，而不是尾随数据。
// 
// ASN。1个整数可以写入int、int32、int64、
// 或*big。Int（来自数学/大软件包）。
// 如果编码的值不适合Go类型，
// 解组返回解析错误。
// 
// ASN。1位字符串可以写入位字符串。
// 
// ASN。1个八位字节字符串可以写入[]字节。
// 
// ASN。1对象标识符可以写入
// 对象标识符。
// 
// ASN。1枚举可写入枚举。
// 
// ASN。1 UTCTIME或GENERALIZEDTIME可以写入一个时间。时间
// 
// ASN。1可打印字符串、IA5String或NumericString可以写入字符串。
// 
// 上述任何ASN。1可以将值写入接口{}。
// 存储在接口中的值具有相应的Go类型。
// 对于整数，该类型为int64。
// 
// ASN。1如果x可以写入片的元素类型，则x序列或x集合可以写入片。
// 
// ASN。如果序列中的每个元素都可以写入结构中的相应元素，则可以将1个序列或集合写入结构
// 中。
// 
// 结构字段上的以下标记对解组具有特殊意义：
// 
// 应用程序指定使用应用程序标记
// private指定使用私有标记
// 默认值：x为可选整数字段设置默认值（仅在还存在可选项时使用）
// explicit指定一个额外的显式标记包装隐式标记
// explicit将该字段标记为ASN。1可选
// set导致一个set，而不是预期的序列类型
// tag:x指定ASN。1个标签号；暗示ASN。1解码ASN时特定于上下文的
// 
// 。在字符串字段中输入1个带有隐式标记的值，
// 解组将默认为可打印字符串，该字符串不支持
// 字符，例如“@”和“&”。要强制进行其他编码，请使用以下
// 标记：
// 
// ia5将字符串作为ASN进行解组。1 IA5String values 
// numeric导致字符串被解组为ASN。1 NumericString值
// utf8导致字符串被解组为ASN。1 UTF8String值
// 
// 如果结构的第一个字段的类型是RawContent，则结构的原始
// ASN1内容将存储在其中。
// 
// 如果切片类型的名称以“SET”结尾，则它被视为
// 在其上设置了“SET”标记。这将导致将类型解释为一个
// x的集合，而不是一个x的序列。这可以用于不能给出结构标记的嵌套切片
// 中。
// 
// 其他ASN。1.类型不受支持；如果遇到它们，
// Unmarshal将返回一个解析错误。
func Unmarshal(b []byte, val any) (rest []byte, err error) {
	return UnmarshalWithParams(b, val, "")
}

// invalidUnmarshalError描述了传递给Unmarshal的无效参数。
// （Unmarshal的参数必须是非零指针。）
type invalidUnmarshalError struct {
	Type reflect.Type
}

func (e *invalidUnmarshalError) Error() string {
	if e.Type == nil {
		return "asn1: Unmarshal recipient value is nil"
	}

	if e.Type.Kind() != reflect.Pointer {
		return "asn1: Unmarshal recipient value is non-pointer " + e.Type.String()
	}
	return "asn1: Unmarshal recipient value is nil " + e.Type.String()
}

// UnmarshalWithParams允许为
// 顶级元素指定字段参数。参数的形式与字段标记相同。
func UnmarshalWithParams(b []byte, val any, params string) (rest []byte, err error) {
	v := reflect.ValueOf(val)
	if v.Kind() != reflect.Pointer || v.IsNil() {
		return nil, &invalidUnmarshalError{reflect.TypeOf(val)}
	}
	offset, err := parseField(v.Elem(), b, 0, parseFieldParameters(params))
	if err != nil {
		return nil, err
	}
	return b[offset:], nil
}
